/**
 * 
 */
package edu.cmu.cs.webapp.ioms.views;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.ISelectionProvider;
import org.eclipse.jface.viewers.ITableLabelProvider;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerSorter;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.ui.IViewSite;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.part.ViewPart;
import org.eclipse.ui.progress.UIJob;

import edu.cmu.cs.webapp.ioms.dao.DataAccessException;
import edu.cmu.cs.webapp.ioms.dao.impl.UserDAOImpl;
import edu.cmu.cs.webapp.ioms.logging.Alerts;
import edu.cmu.cs.webapp.ioms.models.User;
import edu.cmu.cs.webapp.ioms.ui.providers.user.UsersTableViewerContentProvider;
import edu.cmu.cs.webapp.ioms.ui.providers.user.UsersTableViewerLabelProvider;
import edu.cmu.cs.webapp.ioms.utils.IOMSUtils;

/**
 * @author Christian
 * 
 */
public class UsersListView extends ViewPart implements ISelectionProvider {
	public static final String ID_VIEW = "edu.cmu.cs.webapp.ioms.views.users";

	private TableViewer viewer;

	private Table table;
	ITableLabelProvider labelProvider;

	private User[] users;

	/**
	 * 
	 */
	public UsersListView() {
		labelProvider = new UsersTableViewerLabelProvider();
	}

	@Override
	public void init(IViewSite site) throws PartInitException {
		super.init(site);
		site.setSelectionProvider(this);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.eclipse.ui.part.WorkbenchPart#createPartControl(org.eclipse.swt.widgets
	 * .Composite)
	 */
	@Override
	public void createPartControl(Composite parent) {
		GridLayout gridLayout = new GridLayout();
		gridLayout.numColumns = 1;
		gridLayout.marginHeight = 2;
		gridLayout.marginWidth = 2;

		parent.setLayout(gridLayout);

		createTableViewer(parent);
	}

	public void createTableViewer(Composite parent) {

		/*
		 * Create table
		 */
		GridData gridData = new GridData();
		gridData.horizontalSpan = 3;
		gridData.grabExcessHorizontalSpace = true;
		gridData.grabExcessVerticalSpace = true;
		gridData.horizontalAlignment = GridData.FILL;
		gridData.verticalAlignment = GridData.FILL;

		table = new Table(parent, SWT.FULL_SELECTION | SWT.BORDER
				| SWT.H_SCROLL | SWT.V_SCROLL);
		table.setLayoutData(gridData);

		table.setHeaderVisible(true);
		table.setLinesVisible(true);

		// id
		TableColumn idColumn = new TableColumn(table, SWT.NONE);
		idColumn.setText("#"); //$NON-NLS-1$
		idColumn.setWidth(60);
		idColumn.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				int sortDirection = IOMSUtils
						.updateSortDirection((TableColumn) e.widget);
				viewer.setSorter(new UserSorter(
						UsersTableViewerLabelProvider.USER_ID,
						sortDirection == SWT.DOWN));
			}
		});

		// login
		TableColumn loginColumn = new TableColumn(table, SWT.NONE);
		loginColumn.setText("Login"); //$NON-NLS-1$
		loginColumn.setWidth(110);
		loginColumn.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				int sortDirection = IOMSUtils
						.updateSortDirection((TableColumn) e.widget);
				viewer.setSorter(new UserSorter(
						UsersTableViewerLabelProvider.LOGIN,
						sortDirection == SWT.DOWN));
			}
		});

		// user name
		TableColumn nameColumn = new TableColumn(table, SWT.NONE);
		nameColumn.setText("User Name"); //$NON-NLS-1$
		nameColumn.setWidth(120);
		nameColumn.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				int sortDirection = IOMSUtils
						.updateSortDirection((TableColumn) e.widget);
				viewer.setSorter(new UserSorter(
						UsersTableViewerLabelProvider.NAME,
						sortDirection == SWT.DOWN));
			}
		});

		// role
		TableColumn roleColumn = new TableColumn(table, SWT.NONE);
		roleColumn.setText("Role"); //$NON-NLS-1$
		roleColumn.setWidth(100);
		roleColumn.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				int sortDirection = IOMSUtils
						.updateSortDirection((TableColumn) e.widget);
				viewer.setSorter(new UserSorter(
						UsersTableViewerLabelProvider.ROLE,
						sortDirection == SWT.DOWN));
			}
		});

		// department
		TableColumn deptColumn = new TableColumn(table, SWT.NONE);
		deptColumn.setText("Department"); //$NON-NLS-1$
		deptColumn.setWidth(180);
		deptColumn.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				int sortDirection = IOMSUtils
						.updateSortDirection((TableColumn) e.widget);
				viewer.setSorter(new UserSorter(
						UsersTableViewerLabelProvider.DEPARTMENT,
						sortDirection == SWT.DOWN));
			}
		});

		// last login
		TableColumn lastLoginColumn = new TableColumn(table, SWT.NONE);
		lastLoginColumn.setText("Last Login"); //$NON-NLS-1$
		lastLoginColumn.setWidth(150);
		lastLoginColumn.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				int sortDirection = IOMSUtils
						.updateSortDirection((TableColumn) e.widget);
				viewer.setSorter(new UserSorter(
						UsersTableViewerLabelProvider.LAST_LOGIN,
						sortDirection == SWT.DOWN));
			}
		});

		/*
		 * Create viewer
		 */
		viewer = new TableViewer(table);
		viewer.setUseHashlookup(true);

		viewer.setLabelProvider(labelProvider);
		viewer.setContentProvider(new UsersTableViewerContentProvider());

		// tableViewer.setComparator(new
		// TableViewerComparator(this.tableViewer));

		refreshUsersView();
	}

	public void refreshUsersView() {

		UIJob refreshJob = new RefreshJob("Refresh");
		refreshJob.setUser(true);
		refreshJob.schedule();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.ui.part.WorkbenchPart#setFocus()
	 */
	@Override
	public void setFocus() {
		// TODO Auto-generated method stub

	}

	@Override
	public void addSelectionChangedListener(ISelectionChangedListener listener) {
		this.viewer.addSelectionChangedListener(listener);
	}

	@Override
	public ISelection getSelection() {
		if (viewer != null) {
			return viewer.getSelection();
		}
		return null;
	}

	@Override
	public void removeSelectionChangedListener(
			ISelectionChangedListener listener) {
		if (viewer != null) {
			viewer.removeSelectionChangedListener(listener);
		}
	}

	@Override
	public void setSelection(ISelection selection) {
		if (viewer != null) {
			viewer.setSelection(selection);
		}
	}

	private class RefreshJob extends UIJob {

		public RefreshJob(String name) {
			super(name);
		}

		@Override
		public IStatus runInUIThread(IProgressMonitor monitor) {
			monitor.beginTask("Refreshing Users List...",
					IProgressMonitor.UNKNOWN);
			try {
				users = new UserDAOImpl().getAllUsers().toArray(new User[0]);

			} catch (DataAccessException e) {
				Alerts.getInstance().detailError("Data Access Error",
						e.getLocalizedMessage(), e);
				return Status.CANCEL_STATUS;
			}

			if (users != null) {
				viewer.setInput(users);
			}

			monitor.done();

			return Status.OK_STATUS;
		}

	}

	private class UserSorter extends ViewerSorter {
		private int columnIndex;
		private final boolean ascending;

		public UserSorter(int criteria, boolean ascending) {
			super();
			this.columnIndex = criteria;
			this.ascending = ascending;
		}

		@SuppressWarnings("unchecked")
		@Override
		public int compare(Viewer viewer, Object e1, Object e2) {
			int result = 0;
			if (e1 instanceof User && e2 instanceof User) {
				result = getComparator().compare(
						labelProvider.getColumnText(e1, columnIndex),
						labelProvider.getColumnText(e2, columnIndex));
			}

			if (!ascending) {
				result = result * -1;
			}
			return result;
		}
	}

}
